#include "nRF24l01P.h"

///**************************************************************************************


//Define the layer1 functions
uint8_t SPI_RD_Reg(nRF24L01_Device* device, uint8_t reg) {
	uint8_t reg_val;

	nRF24L01_SPI_NSS_L(device);      // CSN low, initialize SPI communication...
	nRF24L01_Delay_us(SPI_DELAY);
	SPIx_write(device->spi_Device, READ_nRF_REG | reg);       // Select register to read from..
	reg_val = SPIx_read_write(device->spi_Device, 0); // ..then read register value
	nRF24L01_SPI_NSS_H(device);         // CSN high, terminate SPI communication

	return (reg_val);        // return register value
}

uint8_t SPI_WR_Reg(nRF24L01_Device* device, uint8_t reg,
		uint8_t value) {
	uint8_t status;

	nRF24L01_SPI_NSS_L(device);
	nRF24L01_Delay_us(SPI_DELAY);	// CSN low, init SPI transaction
	status = SPIx_read_write(device->spi_Device, WRITE_nRF_REG | reg);	// select register
	SPIx_write(device->spi_Device, value);          // ..and write value to it..
	nRF24L01_SPI_NSS_H(device);                   // CSN high again
	nRF24L01_Delay_us(SPI_DELAY); //wait for the next spi bus transaction to be correct
	return (status);            // return nRF24L01 status uint8_t
}

uint8_t SPI_Read_Buf(nRF24L01_Device* device, uint8_t reg,
		uint8_t *pBuf, uint8_t length) {
	unsigned int status, i;

	nRF24L01_SPI_NSS_L(device);              // Set CSN low, init SPI tranaction
	nRF24L01_Delay_us(SPI_DELAY);
	status = SPIx_read_write(device->spi_Device, READ_nRF_REG | reg); // Select register to write to and read status uint8_t

	for (i = 0; i < length; i++) {
		pBuf[i] = SPIx_read_write(device->spi_Device, 0);

	}

	nRF24L01_SPI_NSS_H(device);
	nRF24L01_Delay_us(SPI_DELAY);	//wait for the next spi bus transaction to be correct

	return (status);                    // return nRF24L01 status uint8_t
}

uint8_t SPI_Write_Buf(nRF24L01_Device* device, uint8_t reg, uint8_t *pBuf, uint8_t length) {
	unsigned int status, i;

	nRF24L01_SPI_NSS_L(device);
	nRF24L01_Delay_us(SPI_DELAY);
	status = SPIx_read_write(device->spi_Device, WRITE_nRF_REG | reg);
	for (i = 0; i < length; i++) //
			{
		SPIx_write(device->spi_Device, *pBuf);
		pBuf++;
	}
	nRF24L01_SPI_NSS_H(device);
	nRF24L01_Delay_us(SPI_DELAY);	//wait for the next spi bus transaction to be correct

	return (status);
}


//Define the laye2:application operation
/****************************************

 All the functions is in "nRF24l01P.h"

 ****************************************/

void nRF24L01_SPI_NSS_H(nRF24L01_Device* device) {
	GPIO_SetBits(device->CSN_GPIO, device->CSN_Pin);
}

void nRF24L01_SPI_NSS_L(nRF24L01_Device* device) {
	GPIO_ResetBits(device->CSN_GPIO, device->CSN_Pin);
}

void nRF24L01_CE_L(nRF24L01_Device* device) {
	GPIO_ResetBits(device->CE_GPIO, device->CE_Pin);
}

void nRF24L01_CE_H(nRF24L01_Device* device) {
	GPIO_SetBits(device->CE_GPIO, device->CE_Pin);
}




void init_nRF24L01(nRF24L01_Device* device) {
	EXTI_ClearITPendingBit(device->IRQ_EXTI_Line);

	InitGPIO(device->CE_GPIO, device->CE_Pin, GPIO_Mode_OUT, GPIO_PuPd_UP,
			GPIO_Speed_50MHz);
	nRF24L01_CE_L(device);
	InitGPIO(device->CSN_GPIO, device->CSN_Pin, GPIO_Mode_OUT, GPIO_PuPd_UP,
			GPIO_Speed_50MHz);
	nRF24L01_SPI_NSS_H(device);
	InitGPIO(device->IRQ_GPIO, device->IRQ_Pin, GPIO_Mode_IN, GPIO_PuPd_UP,
			GPIO_Speed_50MHz);
	Attach_GPIO_Interrupt(device->IRQ_GPIO_PortSource,
			device->IRQ_GPIO_PinSource, device->IRQ_EXTI_Line,
			EXTI_Trigger_Falling, 0x0f);
	/* Initialize spi module */
	device->spi_Device->SPI_Direction = DEFAULT_SPI_Direction;
	device->spi_Device->SPI_Mode = DEFAULT_SPI_Mode;
	device->spi_Device->SPI_DataSize = DEFAULT_SPI_DataSize;
	device->spi_Device->SPI_CPOL = DEFAULT_SPI_CPOL;
	device->spi_Device->SPI_CPHA = DEFAULT_SPI_CPHA;
	device->spi_Device->SPI_NSS = DEFAULT_SPI_NSS;
	device->spi_Device->SPI_BaudRatePrescaler = DEFAULT_SPI_BaudRatePrescaler;
	device->spi_Device->SPI_FirstBit = DEFAULT_SPI_FirstBit;
	device->spi_Device->SPI_CRCPolynomial = DEFAULT_SPI_CRCPolynomial;

	init_SPIx(device->spi_Device);

	SPI_CalculateCRC(device->spi_Device->SPIx, DISABLE);

}

void nRF24L01_Delay_us(unsigned long n) {
	unsigned long i;

	while (n--)  // delay n us
	{
		i = 25;
		while (i--)
			; // delay 1 us
	}
}

uint8_t nRF24L01_setTXAddress(nRF24L01_Device* device, uint8_t* address) {
	return SPI_Write_Buf(device, TX_ADDR, address, ADR_WIDTH); // write address into tx_add
}

uint8_t nRF24L01_setRXAddress(nRF24L01_Device* device, uint8_t pipe, uint8_t* address) {
	if(pipe == PIPE_0){
		return SPI_Write_Buf(device, RX_ADDR_P0, address, ADR_WIDTH); // write address into rx_add_p0
	}else if(pipe == PIPE_1){
		return SPI_Write_Buf(device, RX_ADDR_P1, address, ADR_WIDTH); // write address into rx_add_p1
	}else if(pipe == PIPE_2){
		return SPI_Write_Buf(device, RX_ADDR_P2, address, 1); // write address into rx_add_p2
	}else if(pipe == PIPE_3){
		return SPI_Write_Buf(device, RX_ADDR_P3, address, 1); // write address into rx_add_p3
	}else if(pipe == PIPE_4){
		return SPI_Write_Buf(device, RX_ADDR_P4, address, 1); // write address into rx_add_p4
	}else if(pipe == PIPE_5){
		return SPI_Write_Buf(device, RX_ADDR_P5, address, 1); // write address into rx_add_pSPI_DELAY
	}
	return -1;
}

uint8_t nRF24L01_set_config(nRF24L01_Device* device, uint8_t mask){
	return SPI_WR_Reg(device, CONFIG, mask);
}

uint8_t nRF24L01_set_auto_ack(nRF24L01_Device* device, uint8_t pipe_mask){
	return SPI_WR_Reg(device, EN_AA, pipe_mask);
}

uint8_t nRF24L01_set_enable_pipe(nRF24L01_Device* device, uint8_t pipe_mask){
	return SPI_WR_Reg(device, EN_RXADDR, pipe_mask);
}

uint8_t nRF24L01_set_address_width(nRF24L01_Device* device, uint8_t address_mask){
	return SPI_WR_Reg(device, SETUP_AW, address_mask);
}

uint8_t nRF24L01_set_retransmission(nRF24L01_Device* device, uint8_t mask){
	return SPI_WR_Reg(device, SETUP_RETR, mask);
}

uint8_t nRF24L01_set_channel(nRF24L01_Device* device, uint8_t channel){
	return SPI_WR_Reg(device, RF_CH, channel);
}

uint8_t nRF24L01_set_rf(nRF24L01_Device* device, uint8_t mask){
	return SPI_WR_Reg(device, RF_SETUP, mask);
}

uint8_t nRF24L01_get_status(nRF24L01_Device* device){
	uint8_t status;
	nRF24L01_SPI_NSS_L(device);
	nRF24L01_Delay_us(SPI_DELAY);	// CSN low, init SPI transaction
    status = SPIx_read_write(device->spi_Device, NOP);
	nRF24L01_SPI_NSS_H(device);
	nRF24L01_Delay_us(SPI_DELAY);
	return (status);

}

uint8_t nRF24L01_flush_rx(nRF24L01_Device* device){
	uint8_t status;
	nRF24L01_SPI_NSS_L(device);
	nRF24L01_Delay_us(SPI_DELAY);
	status = SPIx_read_write(device->spi_Device, FLUSH_RX);
	nRF24L01_SPI_NSS_H(device);
	nRF24L01_Delay_us(SPI_DELAY);
	return status;
}

uint8_t nRF24L01_flush_tx(nRF24L01_Device* device){
	uint8_t status;
	nRF24L01_SPI_NSS_L(device);
	nRF24L01_Delay_us(SPI_DELAY);
	status = SPIx_read_write(device->spi_Device, FLUSH_TX);
	nRF24L01_SPI_NSS_H(device);
	nRF24L01_Delay_us(SPI_DELAY);
	return status;
}

uint8_t nRF24L01_get_fifo_status(nRF24L01_Device* device, uint8_t* fifo_status){
	return SPI_Read_Buf(device, FIFO_STATUS, fifo_status, 1);
}

uint8_t nRF24L01_get_payload_length(nRF24L01_Device* device, uint8_t* length){
	return SPI_Read_Buf(device, RD_RX_PL_WID, length, 1);
}

uint8_t nRF24L01_set_status(nRF24L01_Device* device, uint8_t mask){
	return SPI_WR_Reg(device, NRFRegSTATUS, mask);
}
